﻿/*------------------------------------------------------------------------

SMART_ARRAY.HPP v3.2

Copyright 楊志賢 CxxlMan, 2008 - 2013
All Rights Reserved


------------------------------------------------------------------------*/

#if !defined(__SMART_ARRAY_HPP_CxxlMan)
#define __SMART_ARRAY_HPP_CxxlMan

#include <stdarg.h>
#include "SMART_PTR.HPP"
//#include <typeinfo>
//#include <iostream>



namespace CxxlMan
{

template<class K> class Smart_Array;
template <typename T>
void cxxlFASTCALL Smart_Array_Create(Smart_Array<T> *SA,...);


// 想了很久才想出來的妙招，在 mart_Array_Package 中
// 可讓 Smart_Array::Create2 被叫到
// 又可讓 物件 通過編譯
class Smart_Array_Base
{
  virtual void cxxlFASTCALL Create2(size_t *Length) = 0;
public:
  template<class T>
  friend class Smart_Array_Package;
};


template<typename T>
class Smart_Array_Package:virtual public cxxlObject
{
  T *arrayObj;
  size_t ArrayLength;

  // Constructor
  Smart_Array_Package(size_t Length,ISpirit *spirit)
    :cxxlObject(spirit)
  {
    ArrayLength = Length;
    arrayObj = new T[Length];

    //std::cout << typeid(arrayObj).name() << std::endl;
    if( dynamic_cast<Smart_Ptr_Base*>(arrayObj) ) // 陣列的元素是 Smart_Array 或 Smart_Ptr
    {
      for(size_t i = 0; i < ArrayLength; ++i)
        static_cast<Smart_Ptr_Base*>((void*)&(arrayObj[i]))->ResetHost(this);
    }
  }

  // Constructor
  Smart_Array_Package(size_t *Length,ISpirit *spirit)
    :cxxlObject(spirit)
  {
    ArrayLength = *Length;
    arrayObj = new T[*Length];

    if( dynamic_cast<Smart_Ptr_Base*>(arrayObj) ) // 陣列的元素是 Smart_Array 或 Smart_Ptr
      for(size_t i = 0; i < ArrayLength; ++i)
      {
        static_cast<Smart_Ptr_Base*>((void*)&(arrayObj[i]))->ResetHost(this);

        if(*(Length+1) > 0) // 最後被包裹的物件不會執行到
          ((Smart_Array_Base*)(arrayObj+i))->Create2(Length+1);
      }
  }

  T *cxxlFASTCALL GetObjArray(void) const
  {
    return arrayObj;
  }

  size_t cxxlFASTCALL Length() const
  {
    return ArrayLength;
  }

public:
  // Destructor
  virtual ~Smart_Array_Package()
  {
    delete [] arrayObj;
  }

  friend class Smart_Array<T>;
};

template<class K>
class Smart_Array:public Smart_Ptr<Smart_Array_Package<K> >,public Smart_Array_Base
{
  // 重新建立指定的 帷數 和 陣列數
  void cxxlFASTCALL Create2(size_t *Length)
  {
    Smart_Array<K> temp(Length,GetSpirit());
    *this = temp;
  }

  // Constructor，並指定建立多少陣列，供 Create2() 用
  Smart_Array(size_t *Array_Length,ISpirit *spirit)
    :Smart_Ptr<Smart_Array_Package<K> >(new Smart_Array_Package<K>(Array_Length,spirit),rootObject)
  {
    _spirit = spirit;
  }

  ISpirit *_spirit;

  ISpirit *GetSpirit()
  {
    return _spirit;
  }

/*
  cxxlFASTCALL operator K*() const
  {
    Smart_Array_Package<K> *R = *this;

    return R->GetObjArray();
  }
*/
public:

  // Constructor，並指定建立多少陣列
  Smart_Array(size_t Array_Length,cxxlObject *Host=rootObject,ISpirit *spirit=Spirit_Easy)
    :Smart_Ptr<Smart_Array_Package<K> >(new Smart_Array_Package<K>(Array_Length,spirit),Host)
  {
    _spirit = spirit;
  }


  // Constructor，建構空陣列
  Smart_Array(cxxlObject *Host = rootObject, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr<Smart_Array_Package<K> >(NULL,Host)
  {
    _spirit = spirit;
  }

  // Constructor
  Smart_Array(Smart_Array_Package<K> *Src,cxxlObject *Host=rootObject, ISpirit *spirit = Spirit_Easy)
    :Smart_Ptr<Smart_Array_Package<K> >(Src,Host)
  {
    if(Src)
      _spirit = Src->GetObjArray();
    else
      _spirit = spirit;
  }

  // Copy Constructor
  Smart_Array(const Smart_Array &Src,cxxlObject *Host=rootObject)
    :Smart_Ptr<Smart_Array_Package<K> >(Src,Host)
  {
    _spirit = Src._spirit;
  }


  // 設定函數
  Smart_Array<K> &cxxlFASTCALL operator=(Smart_Array_Package<K> *pArray_Package)
  {
    Smart_Ptr<Smart_Array_Package<K> >::operator=(pArray_Package);
    if(pArray_Package)
      _spirit = pArray_Package->GetObjArray();
    return *this;
  }

  // 重新建立指定的陣列數
  void cxxlFASTCALL Create(size_t Array_Length)
  {
    Smart_Array<K> temp(Array_Length,rootObject,GetSpirit());
    *this = temp;
  }

  K &cxxlFASTCALL operator[](int Index)
  {
    Smart_Array_Package<K> *R = *this;

    return R->GetObjArray()[Index];
  }

  const K &cxxlFASTCALL operator[](int Index) const
  {
    Smart_Array_Package<K> *R = *this;

    return R->GetObjArray()[Index];
  }

  // 取得有多少元素個數，須非空陣列才有效
  size_t cxxlFASTCALL Length() const
  {
    if( this->isNULL() )
      return 0;
    else
    {
      Smart_Array_Package<K> *R = *this;
      return R->Length();
    }
  }

  template <typename T>
  friend void cxxlFASTCALL Smart_Array_Create(Smart_Array<T> *SA,...);
};

template <typename T>
void cxxlCDECL Smart_Array_Create(Smart_Array<T> *SA,...)
{
  va_list arg;

  va_start(arg, SA);

  SA->Create2((size_t *)arg);

  va_end(arg);
}


}   /* namespace CxxlMan */
#endif
